import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="For Developers/Best Practices" />

⚠️This document is deprecated. There might still be some good ideas in here but it needs to be sorted out with the current state of the design system.⚠️


# Best Practices

## Creating Flexibile but Focused Components

We want to make components adaptable, while keeping them easy to use.

### Components should adapt to their data.

Missing a title property? The component should display without it's title block. No author property? Hide the author area. And so on. Using a component with no properties shouldn't cause any console errors. This lets components provide flexibility without extra variants or properties.

```html
{{#if @title}}
	<h2>{{@title}}</h2>
{{/if}}
```

Sometimes you might need to provide

```html
<div class="card {{#unless @image mod-no-image}}">
  {{!-- ... --}}
</div>
```

### Provide presentation options using modifier classes

Use modifier classes to provide styling options for components.

Here's a example of a button that has `secondary` and `large` variants.

```css
.button {
	border: none;
	color: rgb(var(--color-text-inverse));
	padding: var(--space-3);
	font-size: var(--font-size-5);
	background-color: var(--color-primary);
}

.button.mod-secondary {
	background-color: var(--color-secondary);
}

.button.mod-large {
	padding: var(--space-4);
	font-size: var(--font-size-8);
}
```

Don't forget to document these classes with stories.

### Use Caution with higher-order components

[Higher order components]() are a powerful pattern that let you build components that can be invoked in a very flexible way. It's handy when you want components that can handle a wide variety of use cases. 

For example, you could make a card component that lets you have multiple images or reverse the order of the title and the image.

```html
<Card as |card|>
	<card.title>{{@article.title}}</card.title>
	<card.image><img src="{{@article.img}}" alt="@article.alt"></card.image>
	<card.desc>@article.caption</card.desc>
</Card>
```

However, this API also makes these components more cumbersome to use and can bloat templates. Therefore, it's recommended to always include sensible defaults when there's no block provided (i.e. when the tag is empty).

```html
<Card @data={{article}} />
```

Furthermore, this level of flexibility is often overkill, especially for components in a design system, which should be a little bit prescriptive about how a component is presented.  Think about, and talk with a designer about the variations you really want to allow, and see if you can provide for them in a more simple way, like a CSS variant class (e.g. `<SimpleCard class="simple-card mod-minimal" />`) or a toggle property `(`@showCloseButton={{true}}`)

### Further reading

[pattern variations](https://bradfrost.com/blog/post/pattern-variations/)

## Handling our Content

### Use adapter helpers to make handling data easier

Radial is designed to serve our content. So it should be easy to use components with our content straight out of the API.  We can use helper functions to make using data straight from the API easier without having to handpick each property

If a component has more than three or four properties that represent data, (title, description, image, etc.), 

```html
<Card
	@image={{@article.leadImage}}
	@tags={{@article.displayTags}}
	@title={{@article.title}}
	@authors={{@article.authors}}
	@body={{or @article.listingSummary @article.description}}
/>

Using an adapter helper, we can declutter long templates.

```html
<Card @data={{wagtail-article-adapter wagtailArticle}} />
```

Provide support for the `@data` property with something like `{{or @title @data.title}}` in the template for your card component.

And a sample adapter helper might look like this:

```js
import { helper } from '@ember/component/helper';

export function wagtailArticleAdapter([article]) {
  return {
	  image: article.leadImage,
	  tags: article.displayTags,
	  title: article.title,
	  authors: article.authors,
	  body: article.listingSummary || article.description,
  }
}

export default helper(wagtailArticleAdapter);
```

## Other Patterns

### Components should expose their events.

Interactive components should expose appropriate events as part of their public interface. Forms, for example, should have `onSubmit` and `onError` properties that a client can hook into. Other components with interactive behaviours should expose events as appropriate. This allows us to hook up things like analytics more easily.

### Handling links.

#### Types of links
The following property names are recommended as hints to what the component can accept.

| Name |Type | Description | Example
|---|---|---|---|
|`url`|`string`| This property only accepts urls, and probably uses an `a` tag internally. | `http://example.com` |
|`route`|`Array`| This accepts a link to an ember route and probably uses {{link-to}} internally.| `['article', 'article-slug']` |
|`link`|`string` OR `Array`| This component can handle links or an ember route arrays. It probably uses the {{link}} helper. | |

#### The link helper
This doesn't exist yet. This lets you automatically treat both internal ember routes (i.e. An array of routing parameters, ['tags', 'mta']) and external urls appropriately, without a lot of extra logic in the clients or components.


```html
<!-- my-component.hbs -->
<h1>{{link @link @linktext}}</h1>
```

## Testing
TODO

## Accessibility
TODO
